/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.facebook.fresco.helper.photoview;

import ohos.aafwk.ability.DataAbilityHelper;
import ohos.aafwk.ability.DataAbilityRemoteException;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DependentLayout;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.PageSliderProvider;
import ohos.agp.components.ScaleInfo;
import ohos.agp.utils.Matrix;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.Size;
import ohos.multimodalinput.event.MmiPoint;
import ohos.multimodalinput.event.TouchEvent;
import ohos.utils.net.Uri;

import com.alexvasilkov.gestures.GestureDetector;
import com.alexvasilkov.gestures.GestureViewInterface;
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
import com.facebook.common.util.UriUtil;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.backends.pipeline.PipelineDraweeControllerBuilder;
import com.facebook.drawee.controller.BaseControllerListener;
import com.facebook.drawee.drawable.Animatable;
import com.facebook.drawee.drawable.ProgressBarDrawable;
import com.facebook.drawee.generic.GenericDraweeHierarchy;
import com.facebook.fresco.helper.Phoenix;
import com.facebook.fresco.helper.ResourceTable;
import com.facebook.fresco.helper.listener.IResult;
import com.facebook.fresco.helper.listener.OnProgressListener;
import com.facebook.fresco.helper.loading.LoadingProgressBarComponent;
import com.facebook.fresco.helper.photoview.entity.PhotoInfo;
import com.facebook.fresco.helper.photoview.photodraweeview.OnPhotoTapListener;
import com.facebook.fresco.helper.photoview.photodraweeview.OnViewTapListener;
import com.facebook.fresco.helper.utils.DensityUtil;
import com.facebook.fresco.helper.utils.MLog;
import com.facebook.imagepipeline.core.ImagePipeline;
import com.facebook.imagepipeline.image.ImageInfo;
import com.github.chrisbanes.photoview.OnScaleChangedListener;
import com.github.chrisbanes.photoview.OnSingleFlingListener;
import com.github.chrisbanes.photoview.OnViewDragListener;
import com.github.chrisbanes.photoview.PhotoView;
import com.github.chrisbanes.photoview.PhotoViewAttacher;
import com.oszc.bbhmlibrary.wrapper.TextUtils;

import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Locale;

/**
 * 图片浏览适配器
 *
 * @author dev
 * @since 2021-08-03
 */
public class PictureBrowseAdapter extends PageSliderProvider {
    private ArrayList<PhotoInfo> mItems;
    private OnPhotoTapListener mOnPhotoTapListener;
    private Component.LongClickedListener mOnLongClickListener;
    private DataAbilityHelper mHelper;

    private int widthPixels;
    private int heightPixels;

    /**
     * 图片浏览适配器
     *
     * @param context 上下文
     * @param items 项目
     * @param photoTapListener 照片点击监听器
     * @param onLongClickListener 在长时间点击监听器
     */
    public PictureBrowseAdapter(Context context, ArrayList<PhotoInfo> items, OnPhotoTapListener photoTapListener,
                                Component.LongClickedListener onLongClickListener) {
        mItems = items;
        mOnPhotoTapListener = photoTapListener;
        mOnLongClickListener = onLongClickListener;
        widthPixels = DensityUtil.getDisplayWidth(context);
        heightPixels = DensityUtil.getDisplayHeight(context);
        mHelper = DataAbilityHelper.creator(context);
    }

    @Override
    public int getCount() {
        return mItems == null ? 0 : mItems.size();
    }

    @Override
    public Object createPageInContainer(ComponentContainer componentContainer, int position) {
        final PhotoInfo photoInfo = mItems.get(position);
        MLog.info("photoInfo.originalUrl = " + photoInfo.getOriginalUrl());
        if (isBigImage(photoInfo)) {
            MLog.info("create Large PhotoView");
            Component contentView = createLargePhotoView(componentContainer.getContext(), photoInfo);
            componentContainer.addComponent(contentView, ComponentContainer.LayoutConfig.MATCH_PARENT,
                ComponentContainer.LayoutConfig.MATCH_PARENT);
            return contentView;
        }
        Component contentView = createPhotoDraweeView(componentContainer.getContext(), photoInfo, position);
        componentContainer.addComponent(contentView, ComponentContainer.LayoutConfig.MATCH_PARENT,
            ComponentContainer.LayoutConfig.MATCH_PARENT);
        return contentView;
    }

    @Override
    public void destroyPageFromContainer(ComponentContainer componentContainer, int position, Object object) {
        if (mItems != null && mItems.size() > 0 && position < mItems.size()) {
            PhotoInfo photoInfo = mItems.get(position);
            if (isBigImage(photoInfo)) {
                final SubsamplingScaleImageView imageView =
                    (SubsamplingScaleImageView) componentContainer.findComponentById(ResourceTable.Id_photo_view);
                if (imageView != null) {
                    imageView.release();
                }
            } else {
                evictFromMemoryCache(photoInfo);
            }
        }
        componentContainer.removeComponent((Component) object);
    }

    @Override
    public boolean isPageMatchToObject(Component component, Object object) {
        return component == object;
    }

    private Component createPhotoDraweeView(Context context, final PhotoInfo photoInfo, int position) {
        Component contentView = LayoutScatter.getInstance(context)
            .parse(ResourceTable.Layout_picture_browse_item, null, false);
        LoadingProgressBarComponent progressBarView =
            (LoadingProgressBarComponent) contentView.findComponentById(ResourceTable.Id_progress_view);
        Component flap = contentView.findComponentById(ResourceTable.Id_flap);
        progressBarView.setProgress(0);
        progressBarView.setText(String.format(Locale.getDefault(), "%d%%", 0));
        progressBarView.setVisibility(Component.VISIBLE);

        PhotoView photoDraweeView =
            (PhotoView) contentView.findComponentById(ResourceTable.Id_photo_drawee_view);

        if (!TextUtils.isEmpty(photoInfo.getUri())) {
            FileDescriptor filedesc = null;
            try {
                filedesc = mHelper.openFile(Uri.parse(photoInfo.getUri()), "r");
                ImageSource.DecodingOptions decodingOpts = new ImageSource.DecodingOptions();
                decodingOpts.desiredSize = new Size();
                if (filedesc != null && filedesc.valid()) {
                    ImageSource imageSource = ImageSource.create(filedesc, null);
                    PixelMap pixelMap = imageSource.createThumbnailPixelmap(decodingOpts, true);
                    photoDraweeView.setPixelMap(pixelMap);
                    flap.setVisibility(Component.HIDE);
                    progressBarView.setVisibility(Component.HIDE);
                }
            } catch (DataAbilityRemoteException | FileNotFoundException error) {
                MLog.error("PictureBrowseAdapter createPhotoDraweeView error " + error.getLocalizedMessage());
            }
        } else {
            if (position == 1) {
                photoDraweeView.setPixelMap(ResourceTable.Media_icon_earth);
                flap.setVisibility(Component.HIDE);
            } else {
                String fileCacheDir = context.getCacheDir().getAbsolutePath();
                Phoenix.with(context).build(photoInfo.getOriginalUrl())
                    .setSmallDiskCache(true)
                    .setDiskCacheDir(fileCacheDir)
                    .setResult(new IResult<PixelMap>() {
                        @Override
                        public void onResult(PixelMap result) {
                            if (result != null) {
                                flap.setVisibility(Component.HIDE);
                                photoDraweeView.setPixelMap(result);
                                setDraweeViewData(flap, photoDraweeView);
                            } else {
                                progressBarView.setProgress(0);
                                progressBarView.setText(String.format(Locale.getDefault(), "%d%%", 0));
                                progressBarView.setVisibility(Component.VISIBLE);
                                flap.setVisibility(Component.VISIBLE);
                            }
                        }

                        @Override
                        public void onProgress(int progress) {
                            progressBarView.setProgress(progress);
                            progressBarView.setText(String.format(Locale.getDefault(), "%d%%", progress));
                            if (progress == 100) {
                                progressBarView.setVisibility(Component.HIDE);
                            }
                        }
                    }).load();
            }
        }
        setDraweeViewData(flap, photoDraweeView);

//        PipelineDraweeControllerBuilder controller = Fresco.newDraweeControllerBuilder();
//        Uri uri = Uri.parse(photoInfo.getOriginalUrl());
//        if (!UriUtil.isNetworkUri(uri)) {
//            uri = new Uri.Builder()
//                .scheme(UriUtil.LOCAL_FILE_SCHEME)
//                .decodedPath(photoInfo.getOriginalUrl())
//                .build();
//        }
//        controller.setUri(uri);
//        GenericDraweeHierarchy hierarchy = photoDraweeView.getHierarchy();
//        hierarchy.setProgressBarImage(new ProgressBarDrawable() {
//            @Override
//            public boolean onLevelChange(int level) {
//                int progress = (int) (((double) level / mMaxValue) * 100);
//                progressBarView.setProgress(progress);
//                progressBarView.setText(String.format(Locale.getDefault(), "%d%%", progress));
//                if (progress == 100) {
//                    progressBarView.setVisibility(Component.HIDE);
//                }
//                return super.onLevelChange(progress);
//            }
//        });

//        controller.setOldController(photoDraweeView.getController());
//        controller.setControllerListener(new BaseControllerListener<ImageInfo>() {
//            @Override
//            public void onFinalImageSet(String id, ImageInfo imageInfo, Animatable animatable) {
//                super.onFinalImageSet(id, imageInfo, animatable);
//                if (imageInfo == null) {
//                    return;
//                }
////                photoDraweeView.update(imageInfo.getWidth(), imageInfo.getHeight());
//            }
//
//            @Override
//            public void onIntermediateImageSet(String id, ImageInfo imageInfo) {
//                super.onIntermediateImageSet(id, imageInfo);
//            }
//        });
//        setDraweeViewData(flap,photoDraweeView, controller);
        return contentView;
    }

    private boolean isZoom;

    private void setDraweeViewData(Component flap, PhotoView photoDraweeView) {
//        photoDraweeView.setController(controller.build());

//        photoDraweeView.setOnPhotoTapListener(new OnPhotoTapListener() {
//            @Override
//            public void onPhotoTap(Component view, float x1, float y1) {
//                if (mOnPhotoTapListener != null) {
//                    mOnPhotoTapListener.onPhotoTap(view, x1, y1);
//                }
//            }
//            @Override
//            public void onPhotoDrag(Component view, TouchEvent event) {
//            }
//        });
        DecimalFormat df = new DecimalFormat("#0.00");
        photoDraweeView.setScaledListener(new Component.ScaledListener() {
            @Override
            public void onScaleStart(Component component, ScaleInfo scaleInfo) {
            }

            @Override
            public void onScaleUpdate(Component component, ScaleInfo scaleInfo) {
                if (!isZoom && Double.parseDouble(df.format(scaleInfo.scale)) <= 0.23) {
                    isZoom = true;
                    photoDraweeView.setScale(photoDraweeView.getMinimumScale()); // 这里还差还原图片之后还可以继续缩放的问题
                }
                if (isZoom) {
                    photoDraweeView.setScale(photoDraweeView.getMinimumScale());
                }

            }

            @Override
            public void onScaleEnd(Component component, ScaleInfo scaleInfo) {
                isZoom = false;
            }
        });

        if (flap.getVisibility() == 2) {
            setCLickListener(photoDraweeView);
            if (mOnLongClickListener != null) {
                photoDraweeView.setLongClickedListener(mOnLongClickListener);
            }
        } else {
            setCLickListener(flap);
        }

//        photoDraweeView.setOnViewTapListener(new OnViewTapListener() {
//            @Override
//            public void onViewTap(Component view, float x1, float y1) {
//                if (mOnPhotoTapListener != null) {
//                    mOnPhotoTapListener.onPhotoTap(view, x1, y1);
//                }
//            }
//        });
    }

    /**
     * 设置点击监听器
     *
     * @param component 皮瓣
     */
    private void setCLickListener(Component component) {
        component.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                if (mOnPhotoTapListener != null) {
                    mOnPhotoTapListener.onPhotoTap(component, 0, 0);
                }
            }
        });
    }


    private Component createLargePhotoView(Context context, final PhotoInfo photoInfo) {
        Component contentView = LayoutScatter.getInstance(context)
            .parse(ResourceTable.Layout_big_image_item, null, false);
        LoadingProgressBarComponent progressBarView =
            (LoadingProgressBarComponent) contentView.findComponentById(ResourceTable.Id_progress_view);
        progressBarView.setProgress(0);
        progressBarView.setText(String.format(Locale.getDefault(), "%d%%", 0));
        progressBarView.setVisibility(Component.VISIBLE);
        LargePhotoView imageView = (LargePhotoView) contentView.findComponentById(ResourceTable.Id_photo_view);
        imageView.setMinScale(1.0f);
        imageView.setMaxRatio(2.0f);
        imageView.setOnProgressListener(new OnProgressListener() {
            @Override
            public void onProgress(int progress) {
                progressBarView.setProgress(progress);
                progressBarView.setText(String.format(Locale.getDefault(), "%d%%", progress));
                if (progress == 100) {
                    progressBarView.setVisibility(Component.HIDE);
                }
            }
        });
        GestureDetector gestureDetector = getGestureDetector(context, imageView);
        imageView.setTouchEventListener(new Component.TouchEventListener() {
            @Override
            public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
                return gestureDetector.onTouchEvent(touchEvent);
            }
        });

        // 加载网络的
        String fileCacheDir = context.getCacheDir().getAbsolutePath();
        Phoenix.with(context)
            .build(photoInfo.getOriginalUrl())
            .setDiskCacheDir(fileCacheDir)
            .setResult(new IResult<PixelMap>() {
                @Override
                public void onResult(PixelMap result) {
                    if (result != null) {
                        imageView.setPixelMap(result);
                    } else {
                        imageView.setVisibility(Component.HIDE);
                    }
                }

                @Override
                public void onProgress(int progress) {
                }
            })
            .load();

        return contentView;
    }


    private GestureDetector getGestureDetector(Context context, LargePhotoView imageView) {
        GestureDetector gestureDetector = new GestureDetector(context,
            new GestureDetector.SimpleOnGestureListener() {
                @Override
                public boolean onSingleTapConfirmed(TouchEvent event) {
                    if (imageView.isReady()) {
                        MmiPoint pointerPosition = event.getPointerScreenPosition(0);
                        if (mOnPhotoTapListener != null) {
                            mOnPhotoTapListener.onPhotoTap(imageView, (int) pointerPosition.getX(), (int) pointerPosition.getY());
                        }
                    } else {
                        MLog.info("onSingleTapConfirmed onError");
                    }
                    return false;
                }

                @Override
                public void onLongPress(TouchEvent event) {
                    if (imageView.isReady()) {
                        if (mOnLongClickListener != null) {
                            mOnLongClickListener.onLongClicked(imageView);
                        }
                    } else {
                        MLog.info("onLongPress onError");
                    }
                }

                @Override
                public boolean onDoubleTap(TouchEvent event) {
                    return false;
                }
            });
        return gestureDetector;
    }

    private void evictFromMemoryCache(PhotoInfo photoInfo) {
        if (!TextUtils.isEmpty(photoInfo.getOriginalUrl())) {
            ImagePipeline imagePipeline = Fresco.getImagePipeline();
            Uri uri = Uri.parse(photoInfo.getOriginalUrl());
            if (imagePipeline.isInBitmapMemoryCache(uri)) {
                imagePipeline.evictFromMemoryCache(uri);
            }
        }
    }


    private boolean isBigImage(PhotoInfo photoInfo) {
        return photoInfo.getWidth() > 2 * widthPixels || photoInfo.getHeight() > 2 * heightPixels;
    }

    /**
     * 回收商
     */
    public void recycler() {
        mOnPhotoTapListener = null;
        mOnLongClickListener = null;
    }
}
